<template>
  <template v-if="props.showFileList">
    <a-upload
      ref="uploadRef"
      :id="uploadUUID"
      :headers="uploadHeaders"
      :action="uploadAction"
      :custom-request="customRequest"
      :data="uploadData"
      :show-file-list="props.showFileList"
      :name="props.name"
      :accept="props.accept"
      :limit="props.limit"
      :multiple="true"
      :list-type="props.listType"
      :image-preview="props.imagePreview"
      :file-list="fileData"
      :custom-icon="uploadCustomIcon()"
      :on-before-upload="uploadBefore"
      @success="uploadSuccess"
      @error="uploadError"
      @change="uploadChange"
      @exceed-limit="uploadLimit"
    />
  </template>
  <template v-else-if="isButton">
    <a-upload
      ref="uploadRef"
      :id="uploadUUID"
      :headers="uploadHeaders"
      :action="uploadAction"
      :custom-request="customRequest"
      :data="uploadData"
      :name="props.name"
      :accept="props.accept"
      @before-upload="uploadBefore"
      @success="uploadSuccess"
      @error="uploadError"
      @change="uploadChange"
    >
    </a-upload>
  </template>
  <template v-else>
    <a-upload
      ref="uploadRef"
      :id="uploadUUID"
      :headers="uploadHeaders"
      :action="uploadAction"
      :custom-request="customRequest"
      :data="uploadData"
      :show-file-list="props.showFileList"
      :name="props.name"
      :accept="props.accept"
      :file-list="singleFileData ? [singleFileData] : []"
      @before-upload="uploadBefore"
      @success="uploadSuccess"
      @error="uploadError"
      @change="uploadChange"
    >
      <template #upload-button>
        <div :class="`arco-upload-list-item${singleFileData && singleFileData.status === 'error' ? ' arco-upload-list-item-error' : ''}`">
          <div
            v-if="singleFileData && singleFileData.url"
            class="arco-upload-list-picture custom-upload-avatar"
            @click.stop
          >
            <img :src="singleFileData.url" />
            <div class="arco-upload-list-picture-mask">
              <a-space>
                <icon-edit @click="againUpload" />
                <icon-eye @click="imagePreviewVisible = true" />
              </a-space>
            </div>
            <a-progress
              v-if="singleFileData.status === 'uploading' && singleFileData.percent < 100"
              :percent="singleFileData.percent"
              type="circle"
              size="mini"
              :style="{
                position: 'absolute',
                left: '50%',
                top: '50%',
                transform: 'translateX(-50%) translateY(-50%)',
              }"
            />
          </div>
          <div v-else class="arco-upload-picture-card">
            <div class="arco-upload-picture-card-text">
              <IconPlus />
              <div v-if="props.uploadText" style="margin-top: 10px; font-weight: 600">{{ props.uploadText }}</div>
            </div>
          </div>
        </div>
      </template>
    </a-upload>
  </template>

  <a-image-preview
    v-model:visible="imagePreviewVisible"
    :src="singleFileData.url"
  />

  <a-modal
    v-model:visible="cropperDialogVisible"
    :title="cropperDialogTitle"
    :modal-style="{ width: '800px', height: '610px' }"
    :body-style="{ height: 'calc(100% - 108px)', overflow: 'auto' }"
    :mask-closable="false"
    @before-ok="cropperDialogBeforeOk"
  >
    <cropper-image ref="cropperRef" :file="cropperImg.url" @cropperOkCallback="cropperOkCBK" />
  </a-modal>
</template>

<script lang="ts" setup>
  import { ref, computed, onMounted, PropType } from 'vue';
  import type { FileItem, ListType, RequestOption } from '@arco-design/web-vue/es/upload/interfaces';
  import { Message } from '@arco-design/web-vue';

  import { useAdminStore } from '@/store';
  import { getToken } from '@/utils/auth';
  import { uploadURL, apiUpload } from '@/api/common';
  import CropperImage from '@/components/cropper/index.vue';

  const props = defineProps({
    // 多文件
    fileList: {
      type: Array,
      default() {
        return [];
      },
    },
    // 单文件
    singleFile: {
      type: Object,
      default() {
        return {
          url: '',
          path: '',
          field: '',
        };
      },
    },
    // 是否显示已上传文件列表
    showFileList: {
      type: Boolean,
      default: true,
    },
    // 上传的文件名
    name: {
      type: String,
      default: 'file',
    },
    // 图片列表类型
    listType: {
      type: String as PropType<ListType>,
      default() {
        return 'picture-card';
      },
    },
    // 是否使用 ImagePreview 组件进行预览
    imagePreview: {
      type: Boolean,
      default: true,
    },
    // 多文件上传数量
    limit: {
      type: Number,
      default: 9,
    },
    // 上传图片大小最大限制(单位：M)
    imageMaxSize: {
      type: Number,
      // default: 500, // 单位：KB
      default: 2,
    },
    // 上传文件大小最大限制(单位：M)
    maxSize: {
      type: Number,
      default: 20,
    },
    // 上传文件类型
    accept: {
      type: String,
      default: 'image/jpeg, image/png, image/gif, text/plain, text/csv, application/vnd.ms-excel, application/msword, application/pdf, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, audio/mp4, video/mp4, aplication/zip', // audio/*, video/*, image/*
    },
    uploadText: {
      type: String,
      default: 'Upload',
    },
    // 是否按钮上传
    isButton: {
      type: Boolean,
      default: false,
    },
    // 按钮上传对应按钮名称
    buttonText: {
      type: String,
      default: '选择文件',
    },
    // 字段，区分同时调用多个组件
    field: {
      type: [Number, String],
      default: 0,
    },
    // 是否剪裁
    cropper: {
      type: Boolean,
      default: true,
    },
  });

  const emit = defineEmits(['uploadCallback']);

  const adminStore = useAdminStore();
  const uploadHeaders = {
    token: getToken(),
  };
  const uploadAction = uploadURL();
  // 上传请求附加的数据
  const uploadData = ref<any>({
    // folder: 'default',
    // place: 'local',
    multi: props.showFileList,
    total_count: props.limit,
    count: 0,
  });
  const uploadRef = ref();
  const allFileDatas = ref<any>([]);
  const uploadUUID = `upload-${(Math.random() * 1000).toFixed(0)}`;
  const imagePreviewVisible = ref(false);

  const cropperRef = ref();
  const cropperDialogVisible = ref(false);
  const cropperDialogTitle = ref('图片剪裁');
  const cropperImg = ref<any>({
    url: '',
  });

  const fileData = computed<any>({
    get() {
      return props.fileList;
    },
    set(val) {
      // emit('uploadCallback', val);
    },
  });
  const singleFileData = computed<any>({
    get() {
      return props.singleFile;
    },
    set(val) {
      // emit('uploadCallback', val);
    },
  });

  // 图片剪裁
  const openCropper = () => {
    cropperDialogVisible.value = true;
    cropperRef.value.initCropper(cropperImg.value.url);
  };
  const cropperOkCBK = (imgUrl: string) => {
    console.log(imgUrl);
  };
  const cropperDialogBeforeOk = (done: any) => {
    cropperDialogVisible.value = false;
    cropperImg.value.url = cropperRef.value.getCropFile();
    done();
  };

  // 上传回调
  const uploadCBK = () => {
    if (props.showFileList) {
      emit('uploadCallback', allFileDatas.value);
    } else {
      emit('uploadCallback', allFileDatas.value[0]);
    }
  };
  // 上传自定义图标
  const uploadCustomIcon = () => {
    return {
      fileName: (file: any) => {
        return `文件名： ${file.name}`;
      },
    };
  };
  const afterSuccess = (response: any) => {
    const fileInfo = {
      uid: new Date().getTime(),
      name: response.data.name,
      url: response.data.src,
      size: response.data.size,
      date: response.data.date,
      filepath: response.data.filepath,
      creatorid: adminStore.id,
      field: props.field,
    };
    if (props.showFileList) {
      if (!allFileDatas.value) {
        allFileDatas.value = fileData.value;
      }
      allFileDatas.value.push(fileInfo);
    } else {
      fileInfo.field = singleFileData.value.field;
      allFileDatas.value = [fileInfo];
    }
    uploadCBK();
  };
  const uploadBefore = (file: any) => {
    let fileMaxSize = props.maxSize;
    if (['image/jpg', 'image/jpeg', 'image/png', 'image/gif'].includes(file.type)) {
      fileMaxSize = props.imageMaxSize;
    }
    // return new Promise((resolve, reject) => {
    //   if (file.size / 1024 / 1024 > 20) {
    //     // reject(new Error(`文件大小请控制在 ${fileMaxSize}M 以内`));
    //     Message.info(`文件大小请控制在 ${fileMaxSize}M 以内`);
    //     resolve(false);
    //   }
    //   resolve(true);
    // });
    if (file.size / 1024 / 1024 > 20) {
      Message.info(`文件大小请控制在 ${fileMaxSize}M 以内`);
      return false;
    }
    return true;
  };
  const customRequest = (options: RequestOption) => {
    const controller = new AbortController();
    (async function requestWrap() {
      const {
        onProgress,
        onError,
        onSuccess,
        fileItem,
        name,
      } = options;
      onProgress(20);
      // if (props.cropper) {
      //   cropperImg.value.url = fileItem.url;
      //   openCropper();
      // }
      const formData = new FormData();
      formData.append(name as string, fileItem.file as Blob);
      const onUploadProgress = (event: ProgressEvent) => {
        let percent;
        if (event.total > 0) {
          percent = (event.loaded / event.total) * 100;
        }
        onProgress(parseInt(String(percent), 10), event);
      };

      await apiUpload(formData, {
        controller,
        onUploadProgress,
      }).then(res => {
        if (res.status === 1) {
          afterSuccess(res);
          onSuccess(res);
        }
      }).catch(error => {
        onError(error);
      });
    })();
    return {
      abort() {
        controller.abort();
      },
    };
  };
  // 放弃【使用 custom-request 进行上传】
  const uploadSuccess = (fileItem: any) => {
    const { response } = fileItem;
    if (response.status === 1) {
      // afterSuccess(response); // 多文件上传只会执行一次
    } else {
      Message.error({
        content: response.msg || 'Error',
      });
    }
  };
  const uploadError = (fileItem: any) => {
    console.log(fileItem);
  };
  const uploadChange = (fileList: FileItem[], fileItem: any) => {
    if (props.showFileList) {
      const { response } = fileItem;
      if (response) {
        // 上传
        if (response.status === 1) {
          allFileDatas.value = fileData.value;
        }
      } else {
        // 删除操作
        allFileDatas.value = fileData.value;
        // const fileInfo = {
        //   uid: fileItem.uid,
        //   name: fileItem.name,
        //   url: fileItem.url,
        //   size: fileItem.size,
        //   date: fileItem.date,
        //   creatorid: fileItem.creatorid,
        // };
        allFileDatas.value.forEach((item: any, index: number) => {
          if (item.uid === fileItem.uid) {
            allFileDatas.value.splice(index, 1);
          }
        });
        uploadCBK();
      }
    }
  };
  const uploadLimit = (fileList: FileItem[], files: any) => {
    Message.warning(`最多上传 ${props.limit} 个文件`);
  };
  const againUpload = () => {
    const dom = document.querySelector(`#${uploadUUID} input`);
    if (dom) {
      dom.addEventListener('click', function (e) {
        console.log('upload');
      }, false);
      dom.dispatchEvent(new MouseEvent('click'));
    }
  };

  onMounted(async () => {
    // console.log(props.singleFile); // 无效
    // console.log(singleFileData);
    console.log(props.fileList);
  });
</script>

<style lang="less">
  .arco-upload-list-item {
    margin-top: 0;
  }
</style>
